/**
 * jQueryEJS 1.0
 * http://jqejs.liuzy88.com/
 * 2017-01-01 liuzy
 */
(function($) {
    /*** customize your method to extend EJS object ***/
    var EJS = {};
    EJS.localDate = function(s) {
        var d = new Date(s);
        return [d.getFullYear(), '-',
            ('0' + (d.getMonth() + 1)).slice(-2), '-',
            ('0' + d.getDate()).slice(-2), ' ',
            ('0' + d.getHours()).slice(-2), ':',
            ('0' + d.getMinutes()).slice(-2), ':',
            ('0' + d.getSeconds()).slice(-2)
        ].join('');
    };
    /*** public method ***/
    var P = {};
    P.selfHTML = function(that) {
        var D = document.createElement('div');
        D.appendChild($.clone(that[0]));
        return D.innerHTML;
    };
    P.open = function(op) {
        return '<%' + (op || '') + ' ';
    };
    P.close = function() {
        return ' %>';
    };
    P.wrap = function(dom) {
        return P.open() + dom + P.close();
    };
    P.wrapV = function(dom) {
        return P.open('=') + dom + P.close();
    };
    P.wrapH = function(dom) {
        return P.open('-') + dom + P.close();
    };
    /*** handling labels with ejs-* ***/
    var et = {};
    et['e-for'] = function(dom, tp) {
        dom.each(function() {
            var before = P.selfHTML($(this));
            console.log('----e-for before----\n', before);
            var after = P.wrap('for(' + $(this).attr('e-for') + ') {') + before + P.wrap('}');
            console.log('----e-for after----\n', after);
            tp = tp.replace(before, after);
        });
        return tp;
    };
    et['e-js'] = function(dom, tp) {
        dom.each(function() {
            var before = P.selfHTML($(this));
            console.log('----e-js before----\n', before);
            var after = P.wrap($(this).attr('e-js')) + before + P.wrap($(this).attr('e-sj'));
            console.log('----e-js after----\n', after);
            tp = tp.replace(before, after);
        });
        return tp;
    };
    et['e-bind'] = function(dom, tp) {
        dom.each(function() {
            var before = P.selfHTML($(this));
            console.log('----e-bind before----\n', before);
            var after = P.selfHTML($(this).html(P.wrapV($(this).attr('e-bind'))));
            console.log('----e-bind after----\n', after);
            tp = tp.replace(before, after);
        });
        return tp;
    };
    /*** ejs template cache, compile, auto compile ***/
    var cache = {
        _data: {},
        set: function(k, v) {
            this._data[k] = v;
        },
        get: function(k) {
            return this._data[k];
        }
    };
    function compile(id, tp) {
        cache.set(id, ejs.compile(tp));
        console.log('ejs template [' + id + '] is compiled, length ' + tp.length + ':\n', tp);
    }
    function autoCompile() {
        $('[ejs]').each(function() {
            var id = $(this).attr('ejs') || $(this).attr('id');
            var tp = $(this).html();
            if (id && tp) {
                console.log('----autocompile----\n', tp);
                for ( e in et) {
                    tp = et[e]($(this).find('[' + e + ']'), tp);
                }
                tp = tp.replace(/&lt;%/g, '<%').replace(/%&gt;/g, '%>');
                tp = tp.replace(/{{/g, '<%= ').replace(/}}/g, ' %>');
                compile(id, tp);
            }
        });
    }
    /*** render ejs template with json ***/
    function render(_this, id, obj, clear) {
        var tp = cache.get(id);
        if (tp) {
            if (obj.EJS == undefined) {
                obj.EJS = $.EJS;
            }
            if (clear === true) {
                _this.html('');
            }
            _this.html(tp(obj));
        } else {
            console.log('ejs template [' + id + '] not found.');
        }
    }
    /*** extend jquery method ***/
    // jquery ejs helper
    $.EJS = EJS;
    // jqeury ejs compile
    $.ejs = function(a) {
        if (arguments.length == 0) {
            autoCompile();
        } else if (arguments.length == 1 && typeof a === 'string' && $(a)) {
            compile(a, $(a).html());
        } else {
            console.log('ejs compile params error.');
        }
    };
    // jqeury ejs render
    $.fn.ejs = function(a, b, c) {
        if (arguments.length == 1 && typeof a === 'object') {
            // render self
            render($(this), $(this).attr('id'), a, false);
        } else if (arguments.length == 2) {
            if (typeof a === 'string' && typeof b === 'object') {
                // render by id
                render($(this), a, b, false);
            } else if (typeof a === 'object' && typeof b === 'boolean') {
                // render by id and clear
                render($(this), $(this).attr('id'), a, b);
            } else {
                console.log('ejs render params error.');
            }
        } else if (arguments.length == 3 && typeof a === 'string' && typeof b === 'object' && typeof c === 'boolean') {
            // render by id and clear
            render($(this), a, b, c);
        } else {
            console.log('ejs render params error.');
        }
    };
})(jQuery)

// example
$(function() {
    var D = document.createElement('div');
    D.appendChild($.clone($('#myDiv')[0]));
    $('pre[class="temp"]').html(D.innerHTML.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n    /g, '\n'));
    $('pre[class="script"]').html($('#myJs').html().replace(/\n    /g, '\n').trim());
    $.ejs();
});
